package com.therouter.apt

import java.io.*
import java.math.BigInteger
import java.security.MessageDigest

/**
 * 文件工具类
 * 
 * 提供文件读写、流处理和 MD5 计算等常用功能。
 * 使用 Kotlin 的 use 函数确保资源正确关闭，避免资源泄漏。
 * 
 * @author zhangtao
 * @since 2019-02-20
 */

/**
 * 将字符串写入文件
 * 
 * @param content 要写入的字符串内容
 * @param file 目标文件
 * @throws IOException 如果写入失败
 */
fun writeStringToFile(content: String, file: File) {
    FileOutputStream(file).use { fileOutputStream ->
        fileOutputStream.write(content.toByteArray())
        fileOutputStream.flush()
    }
}

/**
 * 从文件中读取文本内容
 * 
 * @param filePath 要读取的文件
 * @return 文件内容字符串，如果读取失败返回 null
 * @throws RuntimeException 如果文件不存在
 */
fun readFile(filePath: File): String? {
    var inputStream: InputStream? = null
    inputStream = try {
        FileInputStream(filePath)
    } catch (e: Exception) {
        throw RuntimeException("FileUtils:readFile---->$filePath not found")
    }
    return inputStream2String(inputStream)
}

/**
 * 输入流转换为字符串
 * 
 * 使用 try-with-resources 确保输入流正确关闭。
 * 
 * @param inputStream 要转换的输入流
 * @return 流中的字符串内容，如果输入流为 null 或读取失败返回 null
 */
fun inputStream2String(inputStream: InputStream?): String? {
    if (null == inputStream) {
        return null
    }
    var resultSb: StringBuilder? = null
    try {
        inputStream.use { stream ->
            BufferedReader(InputStreamReader(stream)).use { br ->
                resultSb = StringBuilder()
                var len: String?
                while (br.readLine().also { len = it } != null) {
                    resultSb?.append(len)
                }
            }
        }
    } catch (ex: Exception) {
        // 忽略异常，返回已读取的内容
    }
    return resultSb?.toString()
}

/**
 * 复制输入流到输出流
 * 
 * @param inputStream 源输入流
 * @param out 目标输出流
 * @throws IOException 如果复制过程中发生错误
 */
@Throws(IOException::class)
fun copyFile(inputStream: InputStream, out: OutputStream) {
    val buffer = ByteArray(1024)
    var read: Int
    while (inputStream.read(buffer).also { read = it } != -1) {
        out.write(buffer, 0, read)
    }
}

/**
 * 计算文件的 MD5 值
 * 
 * 使用 try-with-resources 确保输入流正确关闭。
 * 
 * @param file 要计算 MD5 的文件
 * @return MD5 值的十六进制字符串，如果文件不存在或计算失败返回 null
 */
fun getMD5(file: File): String? {
    if (!file.isFile) {
        return null
    }
    return try {
        val digest = MessageDigest.getInstance("MD5")
        FileInputStream(file).use { inputStream ->
            val buffer = ByteArray(1024)
            var len: Int
            while (inputStream.read(buffer, 0, 1024).also { len = it } != -1) {
                digest.update(buffer, 0, len)
            }
        }
        val bigInt = BigInteger(1, digest.digest())
        bigInt.toString(16)
    } catch (e: Exception) {
        null
    }
}

/**
 * 关闭可关闭资源
 * 
 * 此方法已废弃，建议使用 Kotlin 的 use 函数来自动管理资源。
 * 
 * @param closeables 需要关闭的资源数组
 * @throws RuntimeException 如果关闭过程中发生错误
 * @deprecated 使用 Kotlin 的 use {} 替代
 */
@Deprecated("Use Kotlin's use {} instead", ReplaceWith("resource.use { }"))
fun closeIO(vararg closeables: Closeable?) {
    if (closeables.isEmpty()) {
        return
    }
    for (cb in closeables) {
        try {
            if (null == cb) {
                continue
            }
            cb.close()
        } catch (e: IOException) {
            throw RuntimeException("FileUtils", e)
        }
    }
}